package com.standbyme.hystrix.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.hystrix.*;
import com.standbyme.hystrix.annotation.DoHystrix;
import com.standbyme.hystrix.config.Constants;
import com.standbyme.hystrix.service.IValueService;
import org.aspectj.lang.ProceedingJoinPoint;

import java.lang.reflect.Method;

public class HystrixValueImpl extends HystrixCommand<Object> implements IValueService {

    private ProceedingJoinPoint proceedingJoinPoint;
    private Method method;
    private DoHystrix doHystrix;

    public HystrixValueImpl() {
        super(Setter
                //设置命令所在的组
                .withGroupKey(HystrixCommandGroupKey.Factory.asKey(Constants.GOVERN_GROUP))
                //命令名称
                .andCommandKey(HystrixCommandKey.Factory.asKey(Constants.GOVERN_KEY))
                //该命令所属线程池的名称，默认使用名称GroupKey作为线程
                .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey(Constants.GOVERN_THREAD_POOL))
                //该命令的一些设置，包括断路器的配置，隔离策略，降级设置，以及一些监控指标等。
                .andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD))
                //关于线程池的配置，包括线程池大小，排队队列的大小等
                .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter().withCoreSize(10)));
    }

    @Override
    protected Object run() throws Exception {
        try {
            return proceedingJoinPoint.proceed();
        } catch (Throwable throwable) {
            return null;
        }
    }

    @Override
    public Object access(ProceedingJoinPoint proceedingJoinPoint, Method method, DoHystrix doHystrix, Object[] args) throws Throwable {

        this.doHystrix = doHystrix;
        this.method = method;
        this.proceedingJoinPoint = proceedingJoinPoint;

        Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(Constants.GOVERN_GROUP))
                .andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(doHystrix.timeoutValue()));

        return this.execute();
    }

    @Override
    protected Object getFallback() {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            return objectMapper.readValue(doHystrix.retureJson(),method.getReturnType());
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return null;
    }
}
